import React, {
  ForwardedRef,
  forwardRef,
  useCallback,
  useContext,
  useEffect,
  useImperativeHandle,
  useMemo,
  useRef,
  useState,
} from 'react';
import { ConfigProvider, Empty, Table } from 'antd';
import { TextWidget } from '@inbiz/react';
import ResizableTitle from './ResizableTitle';
import ResizeObserver from 'rc-resize-observer';
import { QueryParam, RecordType, TableCtxType, TablePreviewProps } from '../../interfaces';
import { arrIsEmpty, ColumnConst, ConnectorEnum, EventsMap, UnitEnum } from '../../shared';
import {commonLang} from '@inbiz/utils'
import {
  useActionReducer,
  useColumnConfig,
  useColumns,
  percentageWidthCount,
  useColumnsWidth,
  useFetchData,
  useFormatColumns,
  useFormItems,
  useInbizPrefixCls,
  useInitSearchRef,
  useResize,
  useGetChild,
  usegetPageDetail,
} from '../../hooks';
import EditCellComponent from './EditCell';
import { InBizTableCtx, InBizTableRefCtx, TableCtx } from '../../context';
import TableModal from './TableModal';
import api from './api';
import TableTop from './TableTop';
import TableBottom from './TableBottom';
import cls from 'classnames';
import DataSetCache from '../../dataSet';
import formatters from '../../formatters';
import {
  ColumnType,
  FilterValue,
  SorterResult,
  TableCurrentDataSource,
  TableRowSelection,
} from 'antd/lib/table/interface';
import { GlobalRegistry } from '@inbiz/core';
import { pickBy, isNull } from 'lodash';
import '../../style.less';
import { onFieldValidateEnd } from '@formily/core';
import { flatten, mergeWith } from 'lodash';
import templateStr from './tooltip';
import ReactDOM from 'react-dom';
import { useDebounceEffect, useThrottleEffect } from 'ahooks';

const InBizTable = (props: TablePreviewProps, ref: ForwardedRef<any>) => {

  const {
    rowSelection,
    autoLoad,
    importUpdate,
    zebraEffect,
    controlId,
    viewMode,
    emit,
    title,
    inbiz,
    selectComponent,
    ...rest
  } = useContext(InBizTableCtx);

  const { attrs, queryFields, actions } = useColumnConfig();
  const formItems = useFormItems();
  const { eventsRef, searchRef } = useContext(InBizTableRefCtx);
  const tablePrefixCls = useInbizPrefixCls('table-show-antd-empty');
  const columns = useFormatColumns();
  const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
  const [clickRow, $clickRow] = useState<string>('');
  const { loading, fetchData, pageData, setPageData } = useFetchData();
  const [display] = useState(false);

  const [inlineEditIndex, $inlineEditIndex] = useState<Array<any>>([]);
  
  const isTargetRef = useRef({
    rowIndex: -1,
    dataIndex: undefined,
    middleIndex: undefined,
  });
  const tooltipRef = useRef<any>();

  const pageRef = useRef({});

  const hasError = useRef(false);

  useInitSearchRef();

  const [schema] = usegetPageDetail();

  const beforeForm = useRef([]);

  const tdRef = useRef([]);

  const inibizCache = useRef({});
  // tablebox的div，用于查找dom节点，将错误信息插入到指定的节点
  const $tableBox = useRef<HTMLDivElement>(null)

  /**
   * 别名映射，与编辑同步
   */
  const anotherNameMap = useMemo(() => {
    const queryList = rest.columnConfig?.queryFields ?? [];
    const keyMap = queryList.reduce((prev, next) => {
      const originName = next['origin_FieldName'].split('$')[1];
      if (originName !== next['value']) {
        prev[next['value']] = originName;
      }

      return prev;
    }, {});
    return keyMap;
  }, [rest.columnConfig]);

  const primaryKey = useMemo(() => {
    return pageData.primary ?? 'id';
  }, [pageData.primary]);

  const relationField = useMemo(() => {
    return pageData.relationField;
  }, [pageData]);

  const models = useMemo(() => {
    return formatters.getModels(queryFields);
  }, [queryFields]);

  const requestData = async (params?: any) => {
    return fetchData(params, tableCacheRef.current.dataSetCache);
  };

  const [queryParam, setQueryParam] = useState<QueryParam>({
    current: 1,
    pageSize: 999,
  });
  const childRef = useGetChild();

  const actionTypeRef = useRef<string>('');

  const tableCacheRef = useRef<any>({ data: pageData.data });
  const newRowSelection: TableRowSelection<RecordType> | undefined = useMemo(() => {
    return rowSelection
      ? {
        selectedRowKeys,
        columnWidth: 50,
        fixed: formItems.widthUnit === UnitEnum.pixel,
        onSelect: (record: RecordType, selected: boolean, selectedRows: RecordType[]) => {
          (emit as any)?.(EventsMap.onSelect, record[primaryKey], selected, selectedRows);
        },
        onSelectAll: (
          selected: boolean,
          selectedRows: RecordType[],
          changeRows: RecordType[],
        ) => {
          (emit as any)?.(EventsMap.onSelectAll, selected, selectedRows, changeRows);
        },
        onChange: (keyList: React.Key[]) => {
          setSelectedRowKeys(keyList);
        },
      }
      : undefined;
  }, [selectedRowKeys, primaryKey]);

  const onRow = (record: RecordType): any => {
    return {
      onClick: (event: MouseEvent) => {
        // 修复点击删除按钮的弹框会触发问题
        if (typeof event?.target?.className !== 'string' || event?.target?.className?.indexOf('ant-popover') != -1) {
          return
        }
        tableCacheRef.current.dataSetCache.clickRowData = record;
        if (childRef.length !== 0) {
          $clickRow(record[primaryKey]);
        }
        childRef.forEach((ele) => {
          // const isAdd = tableCacheRef.current.dataSetCache.cacheAddKeyList.includes(record.id);
          inbiz?.(ele).load({
            ...record,
            id: record[relationField] || record[primaryKey],
            $$primary: record[primaryKey],
            _create: record._create,
          });
        });
        (emit as any)?.(EventsMap.onClick, 'tableRowClick', record, event);
      },
      onDoubleClick: (event: MouseEvent) => {
        (emit as any)?.(EventsMap.onDblClickRow, record, event);
      },
    };
  };

  const modalRef = useRef<any>({});

  const finishEdit = useCallback(async () => {
    if (
      actionTypeRef.current !== 'icon' &&
      inlineEditIndex[0] === isTargetRef.current.rowIndex &&
      (inlineEditIndex[1] === isTargetRef.current.dataIndex ||
        isTargetRef.current.dataIndex === '$$all')
    ) {
      isTargetRef.current = {
        rowIndex: -1,
        dataIndex: undefined,
        middleIndex: isTargetRef.current.middleIndex,
      };
      const keys = Object.keys(pageRef.current);
      let keyList = {};
      keys.forEach((ele) => {
        const currentPage = pageRef.current[ele]['page'].getValue();
        if (Object.keys(currentPage)[0]) {
          keyList = {
            ...keyList,
            [schema.contorIdToAttr[Object.keys(currentPage)[0]]]:
              currentPage[Object.keys(currentPage)[0]],
          };
        }
      });

      props.emit?.(
        'onCurrentData',
        keyList,
        pageData.data?.length - 1,
        isTargetRef.current.middleIndex,
      );

    } else if (actionTypeRef.current !== 'icon' && inlineEditIndex.length > 0) {
      const _errorList: Array<any> = [];
      let isError = false;
      beforeForm.current?.forEach((ele, index) => {
        var state = ele?.getState()?.errors ?? [];
        _errorList.push(state);
        if (state.length > 0 && !isError) {
          const error = state.map((child) => child.messages);
          const keys = Object.keys(ele.fields ?? {});
          const field = ele.fields?.[keys[0]];
          isError = true;
          setToolTip(error, tdRef.current[index], field);
        }
      });
      if (flatten(_errorList).length === 0) {
        if (tableCacheRef.current) {
          tableCacheRef.current.hasError = false;
        }
        hasError.current = false;
        if (inlineEditIndex.length > 0) {
          beforeForm.current = [];
          await saveEditInline();
        }
      } else if (inlineEditIndex[1] === '$$all') {
        if (tableCacheRef.current) {
          tableCacheRef.current.hasError = true;
        }
        hasError.current = true;
      }
      if (!(inlineEditIndex[1] === '$$all' && hasError.current)) {
        $inlineEditIndex([]);
      }
    }
    actionTypeRef.current = '';
  }, [inlineEditIndex])

  useImperativeHandle(
    ref,
    () => ({
      ...api(eventsRef, props),
      setSelect: (ids: any) => {
        const keys = Array.isArray(ids) ? ids : [ids];
        setSelectedRowKeys(keys);
      },
      load: async (param: {
        id: string;
        $$primary?: string;
        _create?: boolean;
        index?: number;
        conditions?: [];
        reset?: boolean
      }) => {
        const expandParam = (await eventsRef?.current?.onInitQueryParams?.()) ?? {};
        tableCacheRef.current.dataSetCache.cacheParent =
          expandParam.primary ?? param.$$primary ?? param.id;
        if (param?._create) {
          const cacheData = tableCacheRef.current.dataSetCache.getAllParentNewData();
          setPageData({ data: cacheData || [], total: cacheData?.length ?? 0 });
        } else if (Object.keys(param).length !== 1) {
          const initParams = expandParam.conditions ?? [
            {
              connector: 'and',
              field: rest.relationField,
              modelName: rest.modelname,
              operator: 'eq',
              value: param.id,
            },
          ];
          searchRef.current.conditions = [
            {
              connector: ConnectorEnum.and,
              index: param?.index ?? 0,
              condition: initParams.map((ele) => ({
                ...ele,
                modelName: rest.modelname,
              })),
            },
            ...(param?.conditions || []),
          ];
          if (param?.reset) {
            tableCacheRef.current.dataSetCache?.cacheDelete?.clear?.()
          }
          requestData();
        }
      },
      getDataSetCache: () => tableCacheRef.current.dataSetCache,
      refresh: () => {
        if (tableCacheRef.current.dataSetCache.cacheParent) {
          requestData();
        } else {
          setPageData({ data: [] });
        }
        tableCacheRef.current.dataSetCache.reset();
      },
      changeDataStatus: (id: string) => {
        tableCacheRef.current.dataSetCache.childSetParentData(id);
      },
      deleAddData: (id: string) => {
        const parentId = tableCacheRef.current.dataSetCache.resetId(id)[1];
        tableCacheRef.current.dataSetCache.parentDelChild(parentId);
      },
      loadData: (data: object[], isDesc?: boolean) => {
        const newData = tableCacheRef.current.dataSetCache.updateData({
          list: data,
          oldList: pageData?.data || [],
          delChildrenAdd,
          changeParentStatus: () => {
            if (selectComponent) {
              const parentIdString = tableCacheRef.current.dataSetCache.cacheParent;
              inbiz?.(selectComponent).changeDataStatus(parentIdString);
            }
          },
          isDesc
        });
        setPageData({ data: newData || [], total: newData?.length || 0 });
      },
      getData: () => {
        return pageData?.data;
      },
      getRows: () => {
        return pageData?.data;
      },
      getSelectedIds: () => {
        return selectedRowKeys;
      },
      getSelectedRowIndex: () => {
        const data: any = [];
        selectedRowKeys.forEach((key) => {
          const cache = pageData.data?.find((item) => item[primaryKey] === key);
          if (cache) {
            data.push({ ...cache });
          }
        });
        return data?.reduce((buf: number[], row: RecordType) => {
          buf.push(row[ColumnConst.index]);
          return buf;
        }, []);
      },
      getSelectedRow: () => {
        const data: any = [];
        selectedRowKeys.forEach((key) => {
          const cache = pageData.data?.find((item) => item[primaryKey] === key);
          if (cache) {
            data.push({ ...cache });
          }
        });
        return data.length > 0 ? data : null;
      },
      openModal: (param: any) => {
        modalRef.current.showModal(true, param);
      },
      closeModal: () => {
        modalRef.current.showModal(false);
      },
      isEditIng: () => { //是否还有存在编辑中的项
        return !!inlineEditIndex?.length;
      },
      getSaveData: () => {
        const beforeData = tableCacheRef.current.dataSetCache.throwChangeValue();

        const entries = Object.entries(anotherNameMap);
        const keys = Object.keys(anotherNameMap).map((ele) =>
          ele.indexOf('$') >= 0 ? ele.split('$')[1] : ele,
        );
        const notNull = (data: any, key: string) =>
          (['$$pid', '_create', 'id', '$$child', 'inBizTableIndex', ...keys].includes(key) &&
            !isNull(data)) ||
          !['$$pid', '_create', 'id', '$$child', 'inBizTableIndex', ...keys].includes(key);
        const nextData = beforeData.map((ele) => {
          entries.forEach(([key, value]) => {
            const realKey = key.indexOf('$') >= 0 ? key.split('$')[1] : key;
            if (realKey !== value) {
              ele[value] = ele[realKey];
              ele[realKey] = null;
            }
          });
          return pickBy(ele, notNull);
        });
        // const nextData=beforeData
        return {
          isError: hasError.current,
          cacheData: [
            {
              controlId: props.controlId,
              data: nextData,
              modelName: props.modelname,
              refField: props.relationField,
              parentModelName: tableCacheRef.current?.dataSetCache?.parentModel,
            },
          ],
        };
      },
      getParams: () => {
        return searchRef.current;
      },
      finishEdit,
      setBtnStatus: (keys: string[], bool: boolean) => {
        const newActions = actions.map(item => {
          if (keys.includes(item.operationflag)) {
            return {
              ...item, 
              show: bool
            }
          }
          return item
        })
        props.inbiz(props.controlId).columnConfig.tableValues.actions = newActions
      }
    }),
    [pageData, selectedRowKeys, finishEdit],
  );

  const [_resizeColumn, setResizeColumn] = useState<boolean>(false);
  const [attrFilters, setAttrFilters] = useState<any>(attrs?.map((attr) => attr.propName));

  const handleTableChange = (
    pagination: any,
    filters: Record<string, FilterValue | null>,
    sorter: SorterResult<RecordType> | SorterResult<RecordType>[],
    extra: TableCurrentDataSource<RecordType>,
  ) => {
    if (extra.action === 'filter') {
      return setAttrFilters(filters?.[ColumnConst.actions]);
    }
    let newQueryParam = { ...queryParam };
    if (extra.action === 'sort' && sorter) {
      let orders = [...(queryParam.orders || [])];
      if (Array.isArray(sorter)) {
        orders = orders.filter((order) => sorter.find((item) => item.field === order.fieldName));
        sorter.forEach((each) => {
          orders = formatters.formatOrders(orders, each, models);
        });
        newQueryParam = { ...queryParam, orders };
      } else {
        orders = orders.filter((order) => sorter.field === order.fieldName);
        newQueryParam = { ...queryParam, orders: formatters.formatOrders(orders, sorter, models) };
      }
    }

    const params = {
      pageInfo: {
        current: newQueryParam.current,
        pageSize: newQueryParam.pageSize,
      },
      orders: newQueryParam.orders,
    };
    searchRef.current = {
      ...searchRef.current,
      ...params,
    };
    const res = requestData(params);

    Promise.resolve(res).then(() => setQueryParam(newQueryParam));
  };

  const changeEditCell = async (rowIndex, dataIndex, tdRef) => {
    const targetData = (pageData.data || []).filter((ele) => ele[primaryKey] === rowIndex)[0] ?? {};
    actionTypeRef.current = 'icon';
    const flag =
      rowIndex === inlineEditIndex[0] &&
      (dataIndex === inlineEditIndex[1] || dataIndex === '$$all');
    if (!flag) {
      const _errorList: Array<any> = {};

      beforeForm.current?.forEach((ele) => {
        var state = ele?.getState()?.errors ?? [];
        const key = Object.keys(ele?.getState()?.values)[0];
        _errorList[key] = flatten(state);
      });
      if (Object.values(_errorList).every((ele) => ele.length === 0)) {
        if (inlineEditIndex.length > 0) {
          await saveEditInline();
        }
        tableCacheRef.current.dataSetCache.cacheStatus('edit', targetData);
        props.emit?.('onCurrentData', targetData, pageData.data?.length - 1, dataIndex);
        $inlineEditIndex([rowIndex, dataIndex]);
        // },0)
      } else if (inlineEditIndex[1] !== '$$all') {
        $inlineEditIndex([rowIndex, dataIndex]);
        props.emit?.('onCurrentData', targetData, pageData.data?.length - 1, dataIndex);
      }
    }
  };

  const setToolTip = (_errorList, singleTdRef, field) => {
    if (tooltipRef.current && inlineEditIndex[1] === '$$all') {
      hasError.current = true;
      if (tableCacheRef.current) {
        tableCacheRef.current.hasError = true;
      }
      const target = tooltipRef.current?.querySelector(
        `div[data-controlId="${field.componentProps.controlId}"]`,
      );
      const isString = flatten(_errorList).every((ele) => typeof ele === 'string');
      target ? tooltipRef.current.removeChild(target) : null;
      tooltipRef.current.innerHTML += templateStr(
        {
          top: singleTdRef.current?.offsetTop + (singleTdRef.current?.offsetHeight / 2),
          left: singleTdRef.current?.offsetLeft + singleTdRef.current?.offsetWidth
        },
        isString ? flatten(_errorList) : [],
        field.componentProps.controlId,
      );
      if (!isString) {
        const contentBox = document.querySelector(
          `div[data-content="${field.componentProps.controlId}"]`,
        );
        const content = <>{flatten(_errorList).map((ele) => ele)}</>;
        ReactDOM.render(content, contentBox);
      }
    }
  };

  const changeBeforeForm = (formData, isBool, singleTdRef) => {
    const id = formData?.getState()?.id || new Date().valueOf();
    if (tooltipRef.current) {
      tooltipRef.current.innerHTML = '';
    }
    formData?.addEffects(id, () => {
      onFieldValidateEnd('*', (field) => {
        const _errorList = field.errors.map((ele) => ele.messages);
        if (_errorList.length > 0) {
          setToolTip(_errorList, singleTdRef, field);
        } else {
          hasError.current = false;
          if (tableCacheRef.current) {
            tableCacheRef.current.hasError = false;
          }
          if (tooltipRef.current) {
            tooltipRef.current.innerHTML = '';
          }
        }
      });
    });
    if (isBool) {
      beforeForm.current.push(formData);
      tdRef.current.push(singleTdRef);
    } else {
      beforeForm.current = [formData];
      tdRef.current = [singleTdRef];
    }
  };

  const saveEditInline = async () => {
    const changeParentStatus = () => {
      if (selectComponent) {
        const parentIdString = tableCacheRef.current.dataSetCache.cacheParent;
        inbiz?.(selectComponent).changeDataStatus(parentIdString);
      }
    };

    const _page = Object.values(pageRef.current);

    const customizer = (oldObj, srcObj) => {
      return {
        ...oldObj,
        ...srcObj,
      };
    };

    const targetData =
      (pageData.data || []).filter((ele) => ele[primaryKey] === inlineEditIndex[0])[0] ?? {};
    if (Object.keys(targetData).length === 0) {
      beforeForm.current = [];
    } else {
      let lastValue = {};
      for (let i = 0; i < _page.length; i++) {
        const { code, values } = await (_page[i]?.page?.validateSubmitData(false, true) ?? {});
        if (code === 0) {
          lastValue = mergeWith(lastValue, values, customizer);
        }
      }
      await tableCacheRef.current.dataSetCache.changeCache(lastValue);
      changeParentStatus();
      tableCacheRef.current.loadCacheData('edit');
    }
    pageRef.current = {};
  };

  useEffect(() => {
    document.body.addEventListener('click', finishEdit);
    return () => {
      document.body.removeEventListener('click', finishEdit);
    };
  }, [inlineEditIndex]);

  const getPageRef = (ref, dataIndex) => {
    if (inlineEditIndex[1] !== '$$all') {
      pageRef.current = {};
    }
    if (schema.keysMap[dataIndex]) {
      pageRef.current[schema.keysMap[dataIndex]] = ref;
    }
  };

  const tdClickHandle = (rowIndex, dataIndex, type) => {
    if (actionTypeRef.current !== 'icon') {
      actionTypeRef.current = 'td';
      isTargetRef.current = {
        rowIndex,
        dataIndex: inlineEditIndex[1] === '$$all' ? '$$all' : dataIndex,
        middleIndex: dataIndex,
      };
    }
  };

  const onInit = (id: string, inbiz: any, index: number, dataIndex: string) => {
    props.emit?.('onEditInit', inbiz, id, dataIndex, index);
    inibizCache.current[id] = inbiz;
  };

  useEffect(() => {
    const isAll = tdRef.current.every((ele) => !ele?.current);
    if (isAll && tooltipRef.current) {
      tooltipRef.current.innerHTML = '';
      hasError.current = false;
      tdRef.current = [];
      beforeForm.current = [];
    }
  }, [pageData.data]);

  const EditCell = useCallback(
    ({ dataIndex, children, rowIndex, ...resetProps }) => {
      return (
        <EditCellComponent
          emit={props.emit}
          dataIndex={dataIndex}
          children={children}
          schema={schema}
          inlineEditIndex={inlineEditIndex}
          rowIndex={rowIndex}
          changeEditCell={changeEditCell}
          changeBeforeForm={changeBeforeForm}
          tdClickHandle={tdClickHandle}
          getPageRef={getPageRef}
          primaryKey={primaryKey}
          inlineEdit={rest.inlineEdit}
          onInit={onInit}
          dataSetCache={tableCacheRef.current.dataSetCache}
          actionTypeRef={actionTypeRef.current}
          viewMode={viewMode}
          editPage={
            props.columnConfig?.tableValues?.actions?.filter(
              (ele) => ele.actionType === 'edit',
            )[0] ?? {}
          }
          readOnly={props.readOnly}
          eventsRef={eventsRef}
          {...resetProps}
        />
      );
    },
    [inlineEditIndex, schema, pageData, props.readOnly,viewMode],
  );
  useEffect(() => {
    const messageBox = document.createElement('div');
    messageBox.className = 'inline-edit-box';
    tooltipRef.current = messageBox;
    $tableBox.current?.querySelector('.ant-table-wrapper')?.appendChild(messageBox)
    return () => {
      $tableBox.current?.querySelector('.ant-table-wrapper')?.removeChild(messageBox)
    };
  }, []);

  const [tableWidth, setTableWidth] = useState<number>(document.body.clientWidth);

  const filteredColumns = useMemo(() => {
    if (!attrFilters || !columns) {
      return columns;
    }
    return columns.filter(
      (column: ColumnType<RecordType>) =>
        column.fixed ||
        attrFilters.includes(column.dataIndex as string) ||
        [ColumnConst.index, ColumnConst.actions].includes(column.dataIndex as string),
    );
  }, [attrFilters, props.readOnly, GlobalRegistry.getDesignerLanguage(), viewMode]);
  const totalWidth = useColumnsWidth([...filteredColumns]);

  const resizedWidth = useRef<{ [key: string]: number }>({}); // 改变宽度后的width

  const mergedColumns = useColumns(tableWidth, totalWidth, filteredColumns, resizedWidth);
  // const scrollX = useScrollX(tableWidth, totalWidth);
  const handleResize = useCallback(
    (index: number) =>
      (e: any, { size }: any) => {
        if (mergedColumns) {
          mergedColumns[index].width = size.width < 100 ? 100 : size.width;
        }
        if (formItems.widthUnit === UnitEnum.percentage) {
          const nextColumns = percentageWidthCount(tableWidth, rowSelection, mergedColumns);
          nextColumns.forEach((ele, index) => {
            mergedColumns[index].width = ele.width;
          });
        }
        resizedWidth.current = mergedColumns.reduce((pre, next) => {
          //@ts-ignore
          pre[next.dataIndex] = next.width;
          return pre;
        }, {}) as { [key: string]: number };

        setResizeColumn((prev) => !prev);
      },
    [mergedColumns, tableWidth],
  );
  useMemo(() => {
    if (arrIsEmpty(mergedColumns)) {
      return;
    }
    const index = mergedColumns?.find(
      (col) => (col as ColumnType<RecordType>).dataIndex === ColumnConst.index,
    );
    if (!index) {
      return;
    }
    const { current, pageSize } = searchRef.current.pageInfo;
    index.render = (text, record, rowIdx) => {
      record[ColumnConst.index] = current && rowIdx + 1 + (current - 1) * (pageSize || 10);
      return record[ColumnConst.index];
    };
  }, [queryParam, mergedColumns]);
  useResize(mergedColumns, handleResize, viewMode);
  const delChildrenAdd = (delData: any) => {
    if (delData[primaryKey] === clickRow) {
      $clickRow('');
    }
    if (childRef.length !== 0 && delData._create) {
      childRef.forEach((ele) => {
        inbiz?.(ele).deleAddData(delData[primaryKey]);
      });
    }
  };
  useEffect(() => {
    if (!tableCacheRef.current.dataSetCache) {
      tableCacheRef.current.dataSetCache = new DataSetCache(eventsRef);
      tableCacheRef.current.dataSetCache.primaryKey = primaryKey;
    }
    tableCacheRef.current = {
      ...tableCacheRef.current,
      keyList: selectedRowKeys,
      setSelect: (keys: any) => {
        setSelectedRowKeys(keys);
      },
      data: pageData.data,
      total: pageData.total,
      refresh: requestData,
      delChildrenAdd: delChildrenAdd,
      loadCacheData,
      anotherNameMap,
      hasError: hasError.current,
      saveEditInline,
      schema,
      ...searchRef.current,
    };
  });

  /**
   * 操作完数据后对分页进行操作
   * @param type 'edit'| 'add'|'delete'|操作类型
   */
  const loadCacheData = (type: string, closeInlineEdit: boolean = false) => {
    const { dataSetCache } = tableCacheRef.current;
    const _pageData = dataSetCache.changePage(type, pageData);
    setPageData(_pageData);
    if (type === 'add' && rest.inlineEdit && !closeInlineEdit) {
      const len = _pageData.data.length;
      $inlineEditIndex([_pageData.data[len - 1][primaryKey], '$$all']);
      tableCacheRef.current.dataSetCache.cacheStatus('edit', _pageData.data[len - 1]);
    }
  };

  /**
   * 初始化查询
   */
  const initDataQuery = async () => {
    const expandParam = (await eventsRef?.current?.onInitQueryParams?.()) ?? {};
    const initParams = expandParam.conditions ?? [
      {
        connector: 'and',
        field: rest.relationField,
        operator: 'eq',
        value: (inbiz?.queryData ?? {})['$relationFieldValue'] ?? (inbiz?.queryData ?? {})['id'],
      },
    ];
    if (autoLoad && !selectComponent && initParams.some((ele) => ele.value)) {
      tableCacheRef.current.dataSetCache.cacheParent =
        expandParam.primary ?? (inbiz?.queryData ?? {})['id'];
      searchRef.current.conditions = [
        {
          connector: ConnectorEnum.and,
          index: 0,
          condition: initParams.map((ele) => ({
            ...ele,
            modelName: rest.modelname,
          })),
        },
      ];
      //@ts-ignore
      requestData().then((res: any) => {
        const record = res?.data?.[0] ?? {};
        if (childRef.length !== 0) {
          $clickRow(record[primaryKey]);
        }
        childRef.forEach((ele) => {
          const isAdd = tableCacheRef.current.dataSetCache.cacheAddKeyList.includes(
            record[primaryKey],
          );
          inbiz?.(ele).load({
            ...record,
            _create: isAdd,
            id: (res.relationField ? record[res.relationField] : null) ?? record[res.primary],
            $$primary: record[res.primary],
          });
        });
      });
    } else {
      //@ts-ignore
      const fields = inbiz?.getFields() ?? [];
      if (selectComponent) {
        fields.forEach((ele: any) => {
          if (ele.componentProps.controlId === selectComponent) {
            tableCacheRef.current.dataSetCache.parentModel = ele.componentProps.modelname;
          }
        });
      }
    }
  };

  useEffect(() => {
    initDataQuery();
  }, []);

  const [state, dispatch] = useActionReducer({
    modalRef,
    tableCacheRef,
  });

  const setRowClass = (record: any) => {
    if (record[primaryKey] === clickRow) {
      return 'subtable-clickrow';
    }
    return '';
  };
  const [locale, $locale] = useState(commonLang[GlobalRegistry.getDesignerLanguage()?.toLocaleLowerCase() as keyof typeof commonLang])
  useEffect(() => {
    $locale(commonLang[GlobalRegistry.getDesignerLanguage()?.toLocaleLowerCase() as keyof typeof commonLang])
  }, [GlobalRegistry.getDesignerLanguage()]);
  const scrollX = () => {
    const sum = mergedColumns.reduce((prev, next) => {
      return prev + Number(next.width ?? 100);
    }, 0);
    if (sum <= tableWidth || formItems.widthUnit === UnitEnum.percentage) {
      return undefined;
    }
    return sum;
  };

  useDebounceEffect(() => {
    setPageData(old => {
      return {
        ...old,
        data: old.data ? [...old.data] : []
      }
    })
  }, [_resizeColumn], {
    wait: 300,
  })

  return (
    <TableCtx.Provider
      value={
        {
          state,
          tableCacheRef,
          dispatch,
          emit,
        } as TableCtxType
      }
    >
      <ResizeObserver
        onResize={({ width }) => {
          resizedWidth.current = {};
          if (formItems.widthUnit === UnitEnum.percentage) {
            setTableWidth(width);
          } else {
            const hasActions = mergedColumns.some(
              (columns: any) => columns.dataIndex === 'inBizTableActions',
            );
            if (hasActions) {
              setTableWidth(width - 200);
            } else {
              setTableWidth(width);
            }
          }
        }}
      >
        <ConfigProvider locale={locale}>
          <TableTop fetchData={requestData} viewMode={viewMode} />
          <div style={{ display: display ? 'none' : undefined }} ref={$tableBox}>
            <Table
              rowKey={primaryKey}
              loading={loading}
              //且非固定列宽度之和不要超过 scroll.x
              scroll={{
                x: scrollX(),
              }}
              className={loading ? cls(tablePrefixCls) : ''}
              columns={mergedColumns}
              pagination={false}
              dataSource={pageData.data || []}
              components={{
                header: {
                  cell: ResizableTitle,
                },
                body: {
                  cell: EditCell,
                },
              }}
              rowSelection={newRowSelection}
              onRow={onRow}
              locale={{
                emptyText: (
                  <Empty
                    image={Empty.PRESENTED_IMAGE_SIMPLE}
                    description={<TextWidget>SubTable.no_data</TextWidget>}
                  />
                ),
              }}
              sticky={true}
              {...rest}
              rowClassName={setRowClass}
              size={props.rowHeight}
              onChange={handleTableChange}
              bordered={true}
            />
          </div>
          <TableBottom readOnly={props.readOnly} viewMode={viewMode} />
        </ConfigProvider>
      </ResizeObserver>
      <TableModal
        ref={modalRef}
        state={state}
        tableCacheRef={tableCacheRef}
        primaryKey={primaryKey}
        relationField={relationField}
      />
      {/* <div ref={tooltipRef}></div> */}
    </TableCtx.Provider>
  );
};

export default forwardRef(InBizTable);
